﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Media;
using xnaGraphics = Microsoft.Xna.Framework.Graphics;
using xna = Microsoft.Xna.Framework;

namespace client.app.gui2
{
    /// <summary>
    /// MainUI.xaml 的交互逻辑
    /// </summary>
    public partial class MainUI : UserControl, IUICanvas
    {
        public bool StopEvent
        {
            get
            {
                var fg = _stopEvent;
                _stopEvent = false;
                return fg;
            }
        }

        List<IDrawCanvas> _canvasList = new List<IDrawCanvas>();
        bool _stopEvent = false;
        comm.Timing _timing = new comm.Timing();

        public MainUI()
        {
            InitializeComponent();

            Width = Conf.WIDTH;
            Height = Conf.HEIGHT;

            Loaded += new RoutedEventHandler((o, e) =>
            {
                UpdateDrawCanvasList();
            });
            ckDebug.Checked += new RoutedEventHandler((o, e) =>
            {
                MainGame.Debug = ckDebug.IsChecked;
            });
            ckDebug.IsChecked = true;
        }

        void EnumVisual(Visual visual, List<IDrawCanvas> canvasList)
        {
            var count = VisualTreeHelper.GetChildrenCount(visual);
            for (int i = 0; i < count; i++)
            {
                var childVisual = (Visual)VisualTreeHelper.GetChild(visual, i);
                if (childVisual != null)
                {
                    if (childVisual is IDrawCanvas)
                    {
                        canvasList.Add((IDrawCanvas)childVisual);
                    }
                    EnumVisual(childVisual, canvasList);
                }
            }
        }

        void UpdateDrawCanvasList()
        {
            var list = new List<IDrawCanvas>();
            EnumVisual(this, list);
            _canvasList = list;
        }

        public void ShowLoading(string text)
        {
            loadingUI.Text = text;
            drawLoading.Display = true;
        }
        public void HideLoading()
        {
            drawLoading.Display = false;
        }
        public void ShowMain()
        {
            gridUI.Children.Clear();
            UpdateDrawCanvasList();

            //mapUI.Show();
        }
        public void ShowHeroList()
        {
            gridUI.Children.Clear();
            gridUI.Children.Add(new DrawUI
            {
                Content = new HeroListUI(),
                HorizontalAlignment = HorizontalAlignment.Center,
                VerticalAlignment = VerticalAlignment.Center
            });
            UpdateDrawCanvasList();
        }

        public bool HitTest(Point point, Func<FrameworkElement, bool> callback = null)
        {
            var pt = MainGame.MainWindow.GetOffset(this);
            point.X -= pt.X;
            point.Y -= pt.Y;
            var el = InputHitTest(point);
            object parent = el;
            while (parent != null)
            {
                if (parent is FrameworkElement)
                {
                    var p = (FrameworkElement)parent;
                    if (callback != null)
                    {
                        if (callback(p))
                        {
                            break;
                        }
                    }
                    if (p == this)
                    {
                        return true;
                    }
                    parent = p.Parent;
                }
                else
                {
                    break;
                }
            }
            return false;
        }
        public void CallMouseEvent(MouseEventType type, Point point)
        {
            var begin = DateTime.Now;
            HitTest(point, el =>
            {
                if (el is IUInput)
                {
                    var iui = (IUInput)el;
                    Dispatcher.BeginInvoke(new Action(() =>
                    {
                        iui.CallMouseEvent(type, point);
                    }));

                    if (iui.StopEvent)
                    {
                        _stopEvent = true;
                    }
                    return true;
                }
                return false;
            });
        }

        public void Update(comm.TimeStat timeStat)
        {
            var cvs = _canvasList.ToArray();
            foreach (var cv in cvs)
            {
                cv.Update(timeStat);
            }

            drawConsole.Display = MainGame.Debug;
            drawInfo.Display = MainGame.Debug;

            if (_timing.GetElapsedTime(timeStat, 2000) > 0)
            {
                #region info
                if (MainGame.MainSpace != null && MainGame.MainSpace.CreateSpaceComplete)
                {
                    tbInfo.Text =
                        "user:" + MainGame.MainSpace.UserId + " player:" + MainGame.MainSpace.PlayerId + " \r\n" +
                        MainGame.UpdateTimeStat.FPS + "/" + MainGame.DrawTimeStat.FPS + " " + MainGame.MainSpace.Ping.Value + "ms texs:" + MainGame.RPackManager.AllTexCount + "\r\n" +
                        "send:" + TcpClient.SendFPS + "(" + Math.Round(TcpClient.SendCurrSize / 1024d, 2) + "kb/" + Math.Round(TcpClient.SendTotalSize / 1024d / 1024d, 2) + "m) \r\n" +
                        "recv:" + TcpClient.ReceiveFPS + "(" + Math.Round(TcpClient.ReceiveCurrSize / 1024d, 2) + "kb/" + Math.Round(TcpClient.ReceiveTotalSize / 1024d / 1024d, 2) + "m) \r\n" +
                        "find:" + MainGame.MainSpace.FindTaskCount + " GUI: " + MainGame.MainWindow.UpdateTimeStat.FPS + "/" + MainGame.MainWindow.DrawTimeStat.FPS + "\r\n" +
                        "loc:" + MainGame.MainSpace.Space.LocMgr.TaskCount + " observer:" + MainGame.MainSpace.Space.LocMgr.ObserverCount + " \r\n" +
                        "my:" + MainGame.MainSpace.Space.MySObjCount + " all:" + MainGame.MainSpace.Space.AllSObjectCount + " draw:" + MainGame.MainSpace.Space.DrawSObjCount;
                }
                else
                {
                    tbInfo.Text = MainGame.MainWindow.UpdateTimeStat.FPS + "/" + MainGame.MainWindow.DrawTimeStat.FPS;
                }
                #endregion
                tbInfo.UpBeginDraw();
            }

            mapUI.Update(timeStat);
        }
        public void Draw(comm.TimeStat timeStat, xnaGraphics.SpriteBatch spriteBatch)
        {
            var cvs = _canvasList.ToArray();
            foreach (var cv in cvs)
            {
                cv.Draw(spriteBatch);
            }

            mapUI.Draw(timeStat, spriteBatch);
        }
    }
}
